package com.tencreat.server.message;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONUtil;
import com.tencreat.common.core.enums.ImMessageType;
import com.tencreat.common.core.enums.ImSessionType;
import com.tencreat.common.core.utils.RabbitSendUtils;
import com.tencreat.common.entity.*;
import com.tencreat.common.service.ImMessageService;
import com.tencreat.common.service.ImSessionService;
import com.tencreat.common.service.ImSettingService;
import com.tencreat.common.service.ImUserService;
import com.tencreat.server.config.NettyConfig;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

/**
 * 消息处理类
 */
@Slf4j
@Component
public class MessageSender {

    @Autowired
    ImUserService imUserService;
    @Autowired
    ImSessionService imSessionService;
    @Autowired
    ImMessageService messageService;
    @Autowired
    ImSettingService settingService;
    @Autowired
    RabbitSendUtils rabbitSendUtils;
    @Autowired
    RedisTemplate redisTemplate;

    public void sendMsg(String content) {
        ImMessage message;
        // 解析消息体
        try {
            message = JSONUtil.parse(content).toBean(ImMessage.class);
        } catch (Exception e) {
            log.error("【IM】消息格式错误:{}", content);
            return;
        }
        // 处理消息
        dealMsg(message);

        sendMsg(message);
    }

    public void sendMsg(ImMessage message) {

        rabbitSendUtils.sendMessage(message);

        // 如果是发给客服, 判断下班时间 发送给接收人
        if (message.getMessageType().getCode() < 20) {
            ImSettingBackground setting = settingService.getBackGroundSetting();
            if (message.getToUser() == 1L && setting.getEnd()) {
                LocalTime now = LocalTime.now();
                LocalTime endTime = LocalTime.parse(setting.getEndTime());
                LocalTime startTime = LocalTime.parse(setting.getStartTime());
                if ((now.isAfter(endTime) || now.isBefore(startTime))) {
                    ImUser toUser = imUserService.getById(message.getToUser());
                    ImMessage newMessage = new ImMessage();
                    newMessage.setSessionId(message.getSessionId());
                    newMessage.setFromUser(toUser.getId());
                    newMessage.setFromAvatar(toUser.getAvatar());
                    newMessage.setToUser(message.getFromUser());
                    newMessage.setToAvatar(message.getFromAvatar());
                    newMessage.setContent(setting.getEndContent());
                    newMessage.setMessageType(ImMessageType.TEXT);
                    newMessage.setSessionType(ImSessionType.SINGLE);
                    // 发送客服下班消息
                    rabbitSendUtils.sendMessage(newMessage);
                }
            }
        }
    }

    @RabbitListener(queues = "base-im.message.name")
    public void msgListener(Message msg, com.rabbitmq.client.Channel channel) throws IOException, ClassNotFoundException {
        ByteArrayInputStream byteInt = new ByteArrayInputStream(msg.getBody());
        ObjectInputStream objInt = new ObjectInputStream(byteInt);
        long deliveryTag = msg.getMessageProperties().getDeliveryTag();

        ImMessage message = (ImMessage) objInt.readObject();

        // 持久化消息, 只持久化对话信息
        messageService.saveMsg(message);

        // 发送给目标
        send(message);

        channel.basicAck(deliveryTag, false);
    }

    /*注册*/
    public void connectActive(ImUser imUser) {
        // 立即添加一个和管理员的会话
        if (imUser.getId() != 1L) {
            ImUserSession imUserSession = imUserService.newUser(imUser);

            // 一天只发送一次
            String sendKey = ImSettingBackground.KEY + "_" + imUser.getId();
            if (!redisTemplate.hasKey(sendKey)) {
                // 发送问候消息
                ImSettingBackground setting = settingService.getBackGroundSetting();
                if (setting.getStart()) {
                    ImMessage message = new ImMessage();
                    message.setContent(setting.getStartContent());
                    message.setMessageType(ImMessageType.TEXT);
                    message.setSessionType(ImSessionType.SINGLE);
                    message.setFromUser(1L); // 管理员
                    message.setFromAvatar(setting.getAdminAvatar()); // 管理员
                    message.setToUser(imUserSession.getUserId());
                    message.setToAvatar(setting.getUserAvatar());
                    message.setSessionId(imUserSession.getSessionId());
                    sendMsg(message);

                    // 当天保存
                    LocalDateTime now = LocalDateTime.now();
                    long between = LocalDateTimeUtil.between(now, LocalDateTimeUtil.endOfDay(now), ChronoUnit.SECONDS);
                    redisTemplate.opsForValue().set(sendKey, 1, between, TimeUnit.SECONDS);
                }
            }
        }
    }

    private void send(ImMessage message) {
        // 发送给目标
        Channel channel = NettyConfig.getUserChannelMap().get(message.getToUser());
        if (null != channel && channel.isActive()) {
            channel.writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(message)));
        }
    }
    private void dealMsg(ImMessage message) {
        //TODO 过滤一些没用的消息， 判断对象字段为空

    }
}
